package com.tbit.main.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.tbit.common.constant.PerformanceTypeConstant;
import com.tbit.common.entity.view.PageResult;
import com.tbit.main.constant.AccountConfigExtConstant;
import com.tbit.main.constant.FaultTypeConstant;
import com.tbit.main.constant.enums.PerformanceBizType;
import com.tbit.main.constant.enums.PerformanceRuleType;
import com.tbit.main.dao.core.AccountUserDao;
import com.tbit.main.dao.log.RepairPerformanceDao;
import com.tbit.main.pojo.*;
import com.tbit.main.pojo.maintain_performance.config.RepairPerformanceConfig;
import com.tbit.main.pojo.maintain_performance.rule.RepairRule;
import com.tbit.main.pojo.maintain_performance.stat.*;
import com.tbit.main.service.AccountConfigExtService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author <a href="mailto:zheng.zebiao@tbit.com.cn">zb</a>
 * @since 2025/3/4
 */
@Slf4j
@Service
@AllArgsConstructor
public class RepairPerformanceService extends ServiceImpl<RepairPerformanceDao, RepairPerformance> {
    final AccountUserDao accountUserDao;
    final AccountConfigExtService configExtService;
    final PerformanceRuleGroupService ruleGroupService;
    final RepairPerformanceLogService performanceLogService;

    public List<PerformanceOverviewResp> queryOverviewPage(PerformanceOverviewReq req,AccountUser loginAccountUser) {
        //getBaseMapper().queryOverviewPage(req);
        List<PerformanceOverviewResp> list = this.getPerformanceList(req,loginAccountUser);

        if (CollUtil.isNotEmpty(list)) {
            String accountUserIds = list.stream()
                    .map(PerformanceOverviewResp::getAccountUserId)
                    .map(String::valueOf)
                    .collect(Collectors.joining(","));
            Map<Integer, AccountUser> accountUserMap = Optional.ofNullable(accountUserDao.getByIds(accountUserIds))
                    .map(x -> x.stream()
                            .collect(Collectors.toMap(AccountUser::getAccountUserId, Function.identity()))
                    )
                    .orElse(Collections.emptyMap());

            for (PerformanceOverviewResp detail : list) {
                // 补充运维人员信息
                AccountUser accountUser = accountUserMap.get(detail.getAccountUserId());
                if (accountUser != null) {
                    detail.setAccountUserName(accountUser.getName());
                    detail.setAccountUserPhone(accountUser.getPhone());
                    detail.setDelFlag(accountUser.getDelFlag());
                }
            }
        }
        return list;
    }

    /**
     * 查询绩效统计
     * @param req
     * @return
     */
    public PerformanceCountResp queryPerformanceCount(PerformanceCountReq req) {
        return getBaseMapper().queryPerformanceCount(req);
    }

    public PageResult<RepairPerformanceDetail> queryDetailPage(PerformanceDetailReq req) {
        try (Page<RepairPerformanceDetail> page = PageHelper.startPage(req.getPageNo(), req.getPageSize())) {
            getBaseMapper().queryDetailPage(req);

            if (CollUtil.isNotEmpty(page)) {
                String accountUserIds = page.getResult().stream()
                        .map(RepairPerformanceDetail::getAccountUserId)
                        .map(String::valueOf)
                        .collect(Collectors.joining(","));
                Map<Integer, AccountUser> accountUserMap = Optional.ofNullable(accountUserDao.getByIds(accountUserIds))
                        .map(x -> x.stream()
                                .collect(Collectors.toMap(AccountUser::getAccountUserId, Function.identity()))
                        )
                        .orElse(Collections.emptyMap());

                for (RepairPerformanceDetail detail : page) {
                    // 补充运维人员信息
                    AccountUser accountUser = accountUserMap.get(detail.getAccountUserId());
                    if (accountUser != null) {
                        detail.setAccountUserName(accountUser.getName());
                        detail.setAccountUserPhone(accountUser.getPhone());
                    }
                }
            }
            return PageResult.convertPage(page.toPageInfo());
        }
    }

    /**
     * 计算并插入绩效
     *
     * @param rl 维修记录
     */
    public void calculateAndInsertPerformance(RepairLog rl) {
        try {
            if (!Objects.equals(rl.getRepairState(), 1)) {
                return;
            }

            // 检查开关
            AccountConfigExt performanceSwitch = configExtService.getParamKey(rl.getAccountId(), AccountConfigExtConstant.REPAIR_PERFORMANCE);
            if (performanceSwitch == null || Objects.equals(performanceSwitch.getParamValue(), "0")) {
                return;
            }

            // 生成新绩效记录
            log.info("[维修绩效] 生成新绩效记录, 维修记录id: {}", rl.getRepairLogId());
            RepairPerformance rp = new RepairPerformance();
            rp.setRepairLogId(rl.getRepairLogId());
            rp.setAccountId(rl.getAccountId());

            // 计算绩效
            RepairPerformanceConfig config = ruleGroupService.selectBizPerformanceConfig(rl.getAccountId(), RepairPerformanceConfig::fromRaw, PerformanceBizType.REPAIR);

            BigDecimal performance = BigDecimal.ZERO;
            StringBuilder detail = new StringBuilder();

            List<RepairPerformanceLog> performanceLogs = new ArrayList<>();
            // 基础绩效
            if (config.getBasic() != null && config.getBasic().getEnabled()) {
                log.info("[维修绩效] 维修记录id: {}, 适用基础绩效", rl.getRepairLogId());
                performance = performance.add(config.getBasic().getValidPerformance());
                detail.append("基础绩效: ")
                        .append(NumberUtil.toStr(config.getBasic().getValidPerformance()))
                        .append(";");
                RepairPerformanceLog performanceLog = new RepairPerformanceLog();
                BeanUtil.copyProperties(rp, performanceLog,"performance", "performanceDetail", "remark");
                performanceLog.setPerformance(config.getBasic().getValidPerformance());
                performanceLog.setPerformanceDetail("基础绩效: "+NumberUtil.toStr(config.getBasic().getValidPerformance())+";");
                performanceLog.setRuleType(PerformanceRuleType.BASIC.getValue());
                performanceLog.setRemark("MAIN-BASIC-基础");
                performanceLogs.add(performanceLog);
            }

            // 维修类型绩效
            if (config.getRepair() != null && config.getRepair().getEnabled()) {
                for (RepairRule subRule : config.getRepair().getSubRules()) {
                    List<Integer> repairTypes = Arrays.stream(rl.getRepairTypes().split(","))
                            .map(Integer::parseInt)
                            .collect(Collectors.toList());
                    for (Integer repairType : repairTypes) {
                        if (subRule.getRepairTypes().contains(repairType)) {
                            log.info("[维修绩效] 维修记录id: {}, 适用维修类型绩效, 维修类型: {}", rl.getRepairLogId(), repairType);
                            performance = performance.add(subRule.getPerformance());
                            detail.append("维修类型绩效: ")
                                    .append(NumberUtil.toStr(subRule.getPerformance()))
                                    .append("(")
                                    .append(FaultTypeConstant.parse(repairType, 3))
                                    .append(");");
                            RepairPerformanceLog performanceLog = new RepairPerformanceLog();
                            BeanUtil.copyProperties(rp, performanceLog,"performance", "performanceDetail", "remark");
                            performanceLog.setPerformance(subRule.getPerformance());
                            performanceLog.setPerformanceDetail("维修类型绩效: "+NumberUtil.toStr(subRule.getPerformance())+"("+FaultTypeConstant.parse(repairType, 3)+");");
                            performanceLog.setRuleType(PerformanceRuleType.REPAIR_TYPE.getValue());
                            performanceLog.setRemark("MAIN-REPAIR_TYPE-维修类型："+FaultTypeConstant.parse(repairType, 3));
                            performanceLogs.add(performanceLog);
                            break;
                        }
                    }
                }
            }

            rp.setPerformance(performance);
            rp.setPerformanceDetail(detail.toString());

            // 绩效记录入库
            save(rp);
            // 保存绩效日志
            if (!performanceLogs.isEmpty()){
                // 填充绩效记录id
                performanceLogs.forEach(performanceLog -> performanceLog.setPerformanceId(rp.getPerformanceId()));
                performanceLogService.insertBatch(performanceLogs);
            }
        } catch (Exception e) {
            log.error("[维修绩效] 计算绩效时发生错误, 维修记录id: {}", rl.getRepairLogId(), e);
        }
    }

    /**
     * 更新维修记录的绩效
     *
     * @param performanceId 绩效记录id
     * @param performance   绩效值
     * @param remark        备注
     */
    @Transactional("logTransactionManager")
    public void updatePerformance(Long performanceId, BigDecimal performance, String remark) {
        RepairPerformance update = getById(performanceId);
        BigDecimal oldPerformance = update.getPerformance();
        update.setPerformanceId(performanceId);
        update.setPerformance(performance);
        update.setRemark(remark);
        update.setPerformanceDetail("人工修改绩效: 总绩效" + NumberUtil.toStr(performance, true));
        update.setPerformanceType(PerformanceTypeConstant.MANUAL);
        updateById(update);
        // 计算新旧绩效差值，用于新增一条绩效日志记录repair_performance_log
        BigDecimal subPerformance = performance.subtract(oldPerformance);
        if (subPerformance.compareTo(BigDecimal.ZERO) == 0) {
            return;
        }
        RepairPerformanceLog log = new RepairPerformanceLog();
        BeanUtil.copyProperties(update, log, "remark");
        log.setPerformance(subPerformance);
        log.setRuleType(PerformanceRuleType.MANUAL.getValue());
        log.setRemark("MAIN-人工修改绩效: " + NumberUtil.toStr(oldPerformance, true) + " -> " + NumberUtil.toStr(performance, true));
        performanceLogService.save(log);
    }

    /**
     * @description: 根据设置的当前用户的运维权限获取绩效数据
     * @author: mo.shanyong
     * @date: 2025/5/12 11:13
     * @param: req
     * @param: loginAccountUser
     * @return: java.util.List<com.tbit.main.pojo.maintain_performance.stat.PerformanceOverviewResp>
     */
    private List<PerformanceOverviewResp> getPerformanceList(PerformanceOverviewReq req,AccountUser loginAccountUser){
        //数据权限（0全部，1仅自己）
        req.setAccountUserId(Objects.equals(loginAccountUser.getRole().getDataPermission(),1) ? loginAccountUser.getAccountUserId() : null);
        return getBaseMapper().queryOverviewPage(req);
    }
}
